/*
*Universidad del Valle de Guatemala
* Jose Pablo Rodriguez
* Julio Maldonado
* Mariana Castillo
* Descripcion: main class
* contiene el arbol de huffman en el que se realiza la codificacion utilizando el heap
*/

package h7;

import java.awt.*;
	import java.awt.event.*;
	import javax.swing.*;
	import java.util.*;
public class HuffTree extends JFrame{
    
    private JLabel labl1, labl2,sim,frecu;
		private JTextField jtab1, jtab2;
		private JButton bintab1,bintab2, codiF, probab, Exit;
		private JPanel intercambio;
		private JTabbedPane jtabpane;
		public LinkedList lista1;
		private Change [] codigo;	
		public Change [] messagee;
		public Change [] menores;
		private Change b,c;
		double longi=0,ent=0,contiene=0;
		public LinkedList lista2;
		JDialog jd;
		int m;
		JLabel label1;
		JLabel label2;
		JLabel label3;
		JTextField field1;
		JTextField field2;
		JTextField field3;
	
		Chain FQ;	
	    Frecuencia frecuencia;	
		EventM evento = new EventM();
	
	public HuffTree()
	{
		//frases que se despliegan en pantalla
		super("Algoritmo de Huffman");
        this.m = 0;
			
		lista1 = new LinkedList();
    	lista2 = new LinkedList();
    	
		jd = new JDialog(this,"Huffman",false);
		
		JLabel etiqueta = new JLabel("Elija una opcion");
		etiqueta.setForeground(Color.black);
		codiF = new JButton("Codificador de frases");
		codiF.setBackground(Color.white);
		codiF.setForeground(Color.black);
		
		
		Exit = new JButton("Salida del Programa");
		Exit.setBackground(Color.blue);
		Exit.setForeground(Color.black);
		
		//  frases
		//se activan los listeners
		codiF.addActionListener(new ActionListener()
		{	
		 public void actionPerformed(ActionEvent r)
	    	{
			 jd.hide();			
			 Frase();		
			 FQ.boton.addActionListener(evento);
		    }
		});
		
		//  boton de frecuencias
		
	

 Exit.addActionListener(new ActionListener()
	{	
		public void actionPerformed(ActionEvent r)
		{
			System.exit(0);
		}
	});	
		
		//Panel inicial
		//se establece el tamano, caracteristicas y las opciones
			intercambio = new JPanel();
			intercambio.add(etiqueta);
			intercambio.add(codiF);
			
			intercambio.add(Exit);
			
			jd.add(intercambio);
			jd.setSize(300,150);
			intercambio.setBackground(Color.white);
			jd.setLocationRelativeTo(null);
		jd.show();		
		this.getContentPane().add(jd);
	}
	
	// frames	
	public void Frase()  // transformacion de strings, frame 1
	{
		FQ = new Chain();
		this.getContentPane().add(FQ);
		this.setSize(550,150);
		this.setLocationRelativeTo(null);
		this.setVisible(true);
	}
	
	public void Frecuencia()   // transformar frecuencias, frmae 2
	{
		JFrame frame = new JFrame();
		frame.setTitle("Codificacion con frecuencias");
		frecuencia = new Frecuencia();
		frame.getContentPane().add(frecuencia);
		frame.setSize(450,150);
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);
	}
		
	public void messagee(String messagee)
	{
	 int n_d_simbolos=2;
    	try
    	 {
   		  n_d_simbolos = 2;
    	   if(n_d_simbolos>1 && n_d_simbolos<10 )
    	    {
    	      CodificaFRASE(messagee);
		      Ejecucion(lista1,(lista1.size()),n_d_simbolos);
		      Mostrar(lista2);
            }else
    	     {
    	        JOptionPane.showMessageDialog(null,"Error, no inserto bien la cantidad");
    	     }    
    	 }catch(NumberFormatException h)
    	  {
    	     JOptionPane.showMessageDialog(null,"Error, no iserto bien los simbolos");
    	  }
    }
    
    public void CodificaFRASE(String frase)//codificador de la frase, encuentra mas grande
    {
    	for(int i=0; i<frase.length() ; i++)
    	{
    	 Change si = new Change();
    	 si.setSim("S"+frase.substring(i,i+1));
    	 si.setProb(1);
    	 int a = 0;
    	 boolean flag = false;
    	 if(lista1.size()>0)
    	  do{
    	     Change so = (Change) lista1.get(a);	
    			if(so.equals(si)){
    				so.setProb(si.getProb());
    				flag = true;
    		}
    	 else if(a==(lista1.size()-1))
    	 {
    		flag = true;
    		lista1.add(si);
    		m++;
    	 }
    	a++;
    	}
    	while((flag == false));
    	 else
    	 {
    	 	lista1.add(si);
    		m++;
    	 }
    	}
    	Change [] messagee = new Change[m];
    	codigo = new Change[m];
    	for(int a = 0 ; a<m ; a++)
    	{
    	   messagee[a] = (Change) lista1.get(a);
    	   codigo[a] = new Change(messagee[a].getSymb(), messagee[a].getProb());
    	   lista2.add(codigo[a]);
    	}
    }
    
    public void CodifFrec(int m, int s)//codificador de las frecuencias
    {
	  	lista2 = new LinkedList();
    	codigo = new Change[m];
    	Change [] messagee = new Change[m];
    	for(int i=0;i<m;i++)
    	{
    	  boolean flag = false;
    	  do
    	  {
    		messagee[i] = new Change("S"+(i+1), Double.parseDouble(JOptionPane.showInputDialog("frecuencia del messagee #" + (i+1))));
    		codigo[i] = new Change("S"+(i+1),messagee[i].getProb());
    		if(messagee[i].getProb()<=1 && messagee[i].getProb()>0)
    		{
    	     lista2.add(codigo[i]);
    	     lista1.add(messagee[i]);
    	     flag = true;
    	    }
    	    else
    	    JOptionPane.showMessageDialog(null,"Ingrese las frecuencias entre 0 y 1");
    	 }while(flag == false);
    	}
    	Ejecucion(lista1,m,s);
    	Mostrar(lista2);
    }
    
    public void Ejecucion(LinkedList sec, int m, int s)
    {
    	Inicio(sec,m);
    	Fin(sec,m,s);
    }
     
    public void MCodigo(Change sy, String c, int m)
    {
	  try
	  {
		Change simbolo = new Change("",0.0);
		for(int i=0;i<sy.getSymb().length(); i++)
		{
			if(sy.getSymb().substring(i,i+1).equals(",")==false && (i+1)<sy.getSymb().length())
				simbolo.setSim(sy.getSymb().substring(i,i+1));
			else if(sy.getSymb().substring(i,i+1).equals(",")==true)
			{
			 for(int a=0; a<lista2.size(); a++)
				if(simbolo.equals(lista2.get(a)))
				{
					simbolo = (Change)lista2.get(a);
					simbolo.setCod(c);
					lista2.remove(a);
					lista2.add(a,simbolo);
				}
			  simbolo = new Change("",0.0);
	 		}
		else if(i==(sy.getSymb().length()-1))
		{
			simbolo.setSim(sy.getSymb().substring((sy.getSymb().length()-1),sy.getSymb().length()));
		for(int a=0; a<lista2.size(); a++)
			if(simbolo.equals(lista2.get(a)))
				{
					simbolo = (Change)lista2.get(a);
					simbolo.setCod(c);
					lista2.remove(a);
					lista2.add(a,simbolo);
				}
		}
	}
	}catch(NullPointerException n){
	}
   }
    
    public void Fin(LinkedList sec, int m, int s)
    {
   		messagee = new Change[m];
   		menores = new Change[s+1];
    	for(int i=0; i<sec.size(); i++)
    	 {
        	messagee[i] = (Change) sec.get(i);
              if((m-i)<=s)
              	{
    				menores[m-i]= messagee[i];
   				 }
    	}	
    	for(int i=1; i<=s; i++)
    	{
    		if(i==s)
    		{
    			MCodigo(menores[i], "0", m);
    		}
    		else if((i-1)==0)
    		{
   				 MCodigo(menores[i], (""+(s-1)), m);
    		}
    		else
    		{
    			MCodigo(menores[i], ""+((i-1)), m);
    		}
    	if(i>1){
    	try{
    		menores[1].setSim(","+menores[i].getSymb());
    		menores[1].setProb(menores[i].getProb());
   			 sec.remove(menores[i]);
    	}catch(NullPointerException n){}
    	}
   	 }
     if(sec.size()>1)
        Ejecucion(sec,((m-s)+1),s);
    }
    
    public void Inicio(LinkedList sec, int m)
    {
   	 for(int i=m; i>1; i--)
    	for(int a=0; a<m ; a++)
    	{
   			if(a<(m-1))
   			{
    		 try
    		 {
   				 b = (Change) sec.get(a);
   			 }catch(Exception e){
    								LinkedList lista = (LinkedList)sec.get(a);
   								    b = new Change();
   								    b.setProb((Double)lista.getLast());
    							}
   		 	try{
    				c = (Change) sec.get(a+1);
    			}catch(Exception e){
    								LinkedList lista = (LinkedList)sec.get(a+1);
    								c = new Change();
    								c.setProb((Double)lista.getLast());
    								}
    		if(b.getProb()<c.getProb())
    		{
    			int posb = lista1.indexOf(b);
    			sec.remove(posb);
    			sec.remove(posb);
    			sec.add(posb, b);
    			sec.add(posb, c);
    		}
    	  }		
     }
  }
    
    public void Mostrar(LinkedList l)
    {
	  JDialog impre = new JDialog();
	  JPanel texto = new JPanel();
	  texto.setLayout(new GridLayout(l.size()+1,4));
	  texto.add(new JLabel("Simbolo"));
	  texto.add(new JLabel("Frecuencias"));
	  texto.add(new JLabel("Codigo"));
	  
	  for(int f=0;f<l.size();f++)
		   {
		   	 Change s=(Change) l.get(f);
		     double v = Double.parseDouble(""+s.getProb());
		   	 contiene=contiene+v;		   			   	
		   }
	  
	for(int i =0 ; i< l.size() ; i++)
	{
		Change s = (Change) l.get(i);
		texto.add(new JLabel());
		texto.add(new JLabel("   "+s.getSymb()));
		texto.add(new JLabel(" "+s.getProb()));	
		texto.setBackground(Color.blue);
		texto.add(new JLabel(" "+s.getCod()));
		
		double g= Double.parseDouble(""+s.getProb());
	       double k=g/contiene;      
		  
		   
	}
	    jd.setVisible(true);
	    impre.add(texto);
    	impre.setTitle("Codificado");
		impre.setSize(400,500);
		impre.setVisible(true);	
		
   }

  public class EventM implements ActionListener
	{
		public void actionPerformed(ActionEvent a)
		{
			String cadena=a.getActionCommand();
			if(cadena.equals("Ejecutar"))
			{
				Chain ss = new Chain();
				if(FQ.cadena.getText()!= "")	
				{
					String messagee=FQ.cadena.getText().toString();
					messagee(messagee);
				}else
				{
					JOptionPane.showMessageDialog(null,"Vacio");
				}
			}
		if(cadena.equals("Procesamiento de datos"))
		{
			try
			{
				int m;
                            m = Integer.parseInt(frecuencia.num_prob.getText());
				int symbols = Integer.parseInt(frecuencia.codigo.getText());
				if (symbols > 1 && symbols < 10)
				{
   					CodifFrec(m, symbols);
   				}
			}catch(NumberFormatException h)
    		{
    			JOptionPane.showMessageDialog(null,"Error, no inserto bien la cantidad de mensajes o simbolos");
    		}
    	}
	 }
   }

public static void main(String[] args)
	{
		HuffTree f;
                    f = new HuffTree();
}

    
    
    
}
